`define TEST(loc, mod, expr) \
    initial begin \
        $display(`"loc mod.expr %b`", mod.expr); \
        $display(`"loc loc.mod.expr %b`", loc.mod.expr); \
        begin /* exciting shadowing */ \
            localparam i = 1'bx; \
            localparam j = 1'bz; \
            $display(`"loc loc.mod.expr %b`", loc.mod.expr); \
        end \
    end

`define TEST_FUNC(loc, mod, expr) `TEST(loc, mod, expr())

`define TEST_TASK(loc, mod, expr) \
    initial begin \
        $display(`"loc mod.expr():`"); \
        mod.expr(); \
        $display(`"loc loc.mod.expr():`"); \
        loc.mod.expr(); \
    end

interface Intf;
    parameter [3:0] P = 1;
    localparam [3:0] L = 2;
    wire [3:0] w;
    assign w = 3;
    modport D(input .x(w + 8'b1));
    function automatic [3:0] F;
        return -1;
    endfunction
    task T;
        $display("T called");
    endtask

    if (1) begin : blk
        parameter [3:0] P = 4;
        localparam [3:0] L = 6;
        reg [3:0] w;
        initial w = 7;
        function automatic [3:0] F;
            return 8;
        endfunction
        task T;
            $display("blk.T called");
        endtask
    end
endinterface

module ModAi(Intf i );
    `TEST(ModAi, i, P)
    `TEST(ModAi, i, L)
    `TEST(ModAi, i, w)
    `TEST_FUNC(ModAi, i, F)
    `TEST_TASK(ModAi, i, T)

    `TEST(ModAi, i, blk.P)
    `TEST(ModAi, i, blk.L)
    `TEST(ModAi, i, blk.w)
    `TEST_FUNC(ModAi, i, blk.F)
    `TEST_TASK(ModAi, i, blk.T)
endmodule

module ModAj(Intf j);
    `TEST(ModAj, j, P)
    `TEST(ModAj, j, L)
    `TEST(ModAj, j, w)
    `TEST_FUNC(ModAj, j, F)
    `TEST_TASK(ModAj, j, T)

    `TEST(ModAj, j, blk.P)
    `TEST(ModAj, j, blk.L)
    `TEST(ModAj, j, blk.w)
    `TEST_FUNC(ModAj, j, blk.F)
    `TEST_TASK(ModAj, j, blk.T)
endmodule

module ModBi(Intf.D i);
    `TEST(ModBi, i, P)
    `TEST(ModBi, i, L)
    `TEST(ModBi, i, x)
endmodule

module ModBj(Intf.D j);
    `TEST(ModBj, j, P)
    `TEST(ModBj, j, L)
    `TEST(ModBj, j, x)
endmodule

module top;
    Intf i();
    ModAi ai(i);
    ModAj aj(i);
    ModBi bi(i);
    ModBj bj(i);

    `TEST(top, i, P)
    `TEST(top, i, L)
    `TEST(top, i, w)
    `TEST_FUNC(top, i, F)
    `TEST_TASK(top, i, T)

    `TEST(top, i, blk.P)
    `TEST(top, i, blk.L)
    `TEST(top, i, blk.w)
    `TEST_FUNC(top, i, blk.F)
    `TEST_TASK(top, i, blk.T)
endmodule
